package framework.forms;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import webdriver.table.Table;

/** Базовый класс для работы с таблицами данных
 */
public class BaseTable extends Table{
    
	//  локаторы
	private String tableHeaderTemplate;
	private String rowHeaderTemplate;
	private String cellHeaderTemplate;
	private String divTemplateByID;
	private String tbodyTemplate;
	private String rowTemplate;
	public String cellTemplate;

	public static HashMap<String, Integer> columnNames = new HashMap<String, Integer>();//перечень колонок для выгрузки
	private static final String COL_PLAN_ZAKUPKI = "План закупки"; // названия колонок для итоговой выгрузки
	private static final String COL_PUBLISH_DATE = "Опубликовано";

	/** Базовый конструктор
	 * @param titleLocator - локатор
	 * @param title - название формы
	 * @param id - id таблицы для извлечения данных
	 */
	public BaseTable(By titleLocator, String title, String id) {
		super(titleLocator, title);
		this.divTemplateByID =String.format(super.divTemplateByID, id);
		this.tbodyTemplate = divTemplateByID + "//tbody";
		this.tableHeaderTemplate = divTemplateByID + "//thead";
		this.rowHeaderTemplate = tableHeaderTemplate+"/tr";
		this.cellHeaderTemplate = "/th";
		this.rowTemplate=tbodyTemplate + "/tr";
		this.cellTemplate = "/td";
		columnNames.clear();
	}

	/** Возвращает массив текстовых значений для выбранной строки в таблице
	 * @param rowLocator - локатор строки
	 * @param cellLocator - локатор типа ячеек (например, /th для заголовков, /td для обычных)
	 * @return - массив текстовых значений ячеек
	 */
	public ArrayList<String> getRowText(String rowLocator, String cellLocator){
		String cellLoc = rowLocator+cellLocator;
		ArrayList<String> rowData = new ArrayList<String>();
		List<WebElement> cells = browser.getDriver().findElements(By.xpath(cellLoc));
		int nbRow = cells.size();
		for(int i=0;i<nbRow;i++) {
			rowData.add(cells.get(i).getText());
		}
		return rowData;
	}

	/** Возвращает массив текстовых значений для всех строк в таблице
	 * @param cellLoc - локатор типа ячеек (например, /th для заголовков, /td для обычных)
	 * @return - массив в массиве - первый массив содержит значения ячеек строки, второй массив - все строки
	 */
	public  ArrayList<ArrayList<String>> getTableContents(String cellLoc){
	    String iterator = "[%s]"+cellLoc; //итератор для прохождения по всем ячейкам строки
	    int nbRow=0;
	    ArrayList<ArrayList<String>> tableData = new ArrayList<ArrayList<String>>(); //массив для хранения значений строки
	    tableData.add(getRowText(rowHeaderTemplate, cellHeaderTemplate));
	    List<WebElement> rows = browser.getDriver().findElements(By.xpath(rowTemplate));
	    nbRow = rows.size();
	    for(int r=0;r<nbRow;r++) {
	    	tableData.add(getRowText(rowTemplate, String.format(iterator, r+1)));
	    }
	    return tableData;
	}

	/** Выводит значения 2д-массива
	 * @param list - 2д-массив
	 */
	public void printTableData (ArrayList<ArrayList<String>> list){
		for (ArrayList<String> s: list){
			info(s.toString());
		}
	}

	/** Находит номер колонки по ее названию в таблице
	 * @param columnName - название колонки,
	 * @return - порядковый номер, начиная с 0
	 */
	public  int getColNumByName (String columnName){
		int colNum = 0;
		List<WebElement> headerRow = browser.getDriver().findElements(By.xpath(rowHeaderTemplate+cellHeaderTemplate));
		int nbRow = headerRow.size();
		for(int j=0;j<nbRow;j++) {
			if (headerRow.get(j).getText().trim().equalsIgnoreCase(columnName))	{
			colNum = j;
			break;
			}
		}
		return colNum;
	}

	/** Сортирует 2д-массив по выбранной по номеру колонке (по умолчанию сортирует по возрастанию даты)
	 * @param list - 2д-массив
	 * @param colNum - порядковый номер колонки, по которой происходит сортировка
	 * @return - 2д-отсортированный массив
	 */
	public ArrayList<ArrayList<String>> sortArrayList (ArrayList<ArrayList<String>> list, int colNum){
		SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy"); // шаблон для парсинга из строки в дату
		int totalRows = list.size();

		for(int i = 0; i< totalRows-1; i++){ // сортировка пузырьком
			for (int j = 1; j<totalRows-i-1;j++){
				 Date d1 = null;
					try {
						String s1 = list.get(j).get(colNum).replace(" (МСК)", ""); // убираем ненужные символы из поля даты
						d1 = sdf.parse(s1);
					} catch (ParseException e1) {
						e1.printStackTrace();
					}
			        Date d2 = null;
					try {
						String s2 = list.get(j+1).get(colNum).replace(" (МСК)", "");  // убираем ненужные символы из поля даты
						d2 = sdf.parse(s2);
					} catch (ParseException e) {
						e.printStackTrace();
					}
					if (d1.after(d2)){ //сравниваем даты, сортируем по возрастанию
						ArrayList<String> tmpArray = new ArrayList<String>();
						tmpArray = list.get(j);
						list.set(j, list.get(j+1));
						list.set(j+1, tmpArray);
					}
			}
		}
		return list;
	}

	/** Оставляет во входном массиве только указанные в массие columnsToExtract[] номера колонок
	 * @param list - 2д-массив
	 * @param map  - карта ключей : название колонки >> порядковый номер
	 * @return - 2д- массив c выбранным набором колонок
	 */
	public ArrayList<ArrayList<String>> exctractArrayList (ArrayList<ArrayList<String>> list, HashMap<String, Integer> map){
		int[] cols = convertToArray(map);
		int totalRows = list.size();
		int totalCols = cols.length;
		ArrayList<ArrayList<String>> newList = new ArrayList<ArrayList<String>>();
		for (int i=0; i<totalRows; i++){
			newList.add(i, new ArrayList<String>());// добавляем новый массив для хранения данных строки таблицы
			for (int j = 0; j<totalCols; j++){
				String s = list.get(i).get(cols[j]);
				if (cols[j]==map.get(COL_PLAN_ZAKUPKI) && i!=0){
					s= substractPlanName(s); // очищаем название плана от ненужных слов
				}
				if (cols[j]==map.get(COL_PUBLISH_DATE) && i!=0){
					s= substractDate(s); // очищаем дату от ненужных символов
				}
				newList.get(i).add(s);
			}
		}
		return newList;
	}

	/** Извлекает название плана
	 * @param s - строка на вход
	 * @return - очищенное название плана
	 */
	public String substractPlanName (String s){
		String newName = s.substring(11, s.indexOf("Период действия"));
		return newName;
	}

	/** Очищает дату публикации
	 * @param s - строка на вход
	 * @return - очищенная дата
	 */
	public String substractDate (String s){
		String newName = s.substring(0, s.indexOf("(МСК"));
		return newName;
	}

	/** Конвертирует HashMap в массив чисел
	 * @param map - карта на вход
	 * @return - массив чисел
	 */
	public int[] convertToArray (HashMap<String, Integer> map){
		int[] newArray = new int[map.size()];
		int index = 0;
		for (Integer mapEntry : map.values()) {
		    newArray[index] = mapEntry.intValue();
		    index++;
		}
		Arrays.sort(newArray);
	    return newArray;
	}
}
